#pragma once

#include "../../Render/Texture/RHITexture.h"
#include "../../Render/Tradition/RHIPipeline.h"
#include "../../Render/Tradition/RHIRenderPass.h"
#include "../../Render/Tradition/RHIFrameBuffer.h"
#include "../../Render/Raytracing/AccelerationStructureGeometry.h"
#include "../../Render/RenderGraph.h"
#include "../../Render/Tradition/RHICommandBuffer.h"
#include "../../Render/Tradition/RHIFence.h"
#include "../../Render/Tradition/RHISemaphore.h"

class GameScene;

#define FIRST_PROCESS "FirstProcess"
#define PREV_PROCESS "PrevProcess"
#define NEXT_PROCESS "NextProcess"
#define LAST_PROCESS "LastProcess"

#define DECLARE_PROCESS(ProcessType) \
	public: \
		virtual std::string GetName() override { return #ProcessType; }; \
		static std::string Name() { return #ProcessType; }

class RenderProcess
{
	friend class RenderState;
	friend class GameScene;
	friend class BufferView;
	friend class CustomBuffer;
	friend class IndexBuffer;
	friend class VertexBuffer;
	friend class AccelerationStructureGeometry;
	friend class BottomLevelAccelerationStructure;
	friend class RayTracingLibrary;
	friend class RayTracingPipeline;
	friend class TopLevelAccelerationStructure;
	friend class RHIDescriptor;
	friend class ColorRenderTarget;
	friend class CubemapTexture;
	friend class CubemapTextureArray;
	friend class CustomTexture;
	friend class ViewTexture;
	friend class DepthRenderTarget;
	friend class Image3DTexture;
	friend class Picture2DTexture;
	friend class Picture2DTextureArray;
	friend class ResolveRenderTarget;
	friend class RHISampler;
	friend class ComputePipeline;
	friend class GraphicsPipeline;
	friend class RHIFrameBuffer;
	friend class RHIRenderPass;
	friend class RHICommandBuffer;
	friend class RHIFence;
	friend class RHISemaphore;

public:

	RenderProcess() {};

	virtual ~RenderProcess();

	virtual std::string GetName() = 0;

protected:

	virtual void OnInit() = 0;

	virtual void OnTick(float deltaTime) = 0;

	virtual void OnResize() = 0;

	virtual void OnFrameEnd() {};

	virtual void OnExit() {};

protected:

	RefCountPtr<RHIBuffer> GetBuffer(const std::string& process, const std::string& name) const;

	RefCountPtr<RHITexture> GetTexture(const std::string& process, const std::string& name) const;

	RefCountPtr<RHIPipeline> GetPipeline(const std::string& process, const std::string& name) const;

	RefCountPtr<RHIRenderPass> GetRenderPass(const std::string& process, const std::string& name) const;

	RefCountPtr<RHIFrameBuffer> GetFrameBuffer(const std::string& process, const std::string& name) const;

	RefCountPtr<RHIDescriptor> GetDescriptor(const std::string& process, const std::string& name) const;

	RefCountPtr<AccelerationStructure> GetAccelerationStructure(const std::string& process, const std::string& name) const;

	RefCountPtr<AccelerationStructureGeometry> GetAccelerationStructureGeometry(const std::string& process, const std::string& name) const;

	RefCountPtr<RHISampler> GetSampler(const std::string& process, const std::string& name) const;

	RefCountPtr<RHICommandBuffer> GetCommandBuffer(const std::string& process, const std::string& name) const;

	RefCountPtr<RHIFence> GetFence(const std::string& process, const std::string& name) const;

	RefCountPtr<RHISemaphore> GetSemaphore(const std::string& process, const std::string& name) const;

protected:

	GameScene* mGameScene;

private:

	RenderProcess* GetProcess(const std::string& name) const;

	const uint32 GetFactIndex(const std::string& name) const;

	void Init(GameScene* gameScene);

private:

	RefCountPtr<RHIBuffer> GetBuffer(const std::string& name) const;

	RefCountPtr<RHITexture> GetTexture(const std::string& name) const;

	RefCountPtr<RHIPipeline> GetPipeline(const std::string& name) const;

	RefCountPtr<RHIRenderPass> GetRenderPass(const std::string& name) const;

	RefCountPtr<RHIFrameBuffer> GetFrameBuffer(const std::string& name) const;

	RefCountPtr<RHIDescriptor> GetDescriptor(const std::string& name) const;

	RefCountPtr<AccelerationStructure> GetAccelerationStructure(const std::string& name) const;

	RefCountPtr<AccelerationStructureGeometry> GetAccelerationStructureGeometry(const std::string& name) const;

	RefCountPtr<RHISampler> GetSampler(const std::string& name) const;

	RefCountPtr<RHICommandBuffer> GetCommandBuffer(const std::string& name) const;

	RefCountPtr<RHIFence> GetFence(const std::string& name) const;

	RefCountPtr<RHISemaphore> GetSemaphore(const std::string& name) const;

private:

	void AddBuffer(const std::string& name, RHIBuffer* buffer);

	void RemoveBuffer(const std::string& name, RHIBuffer* buffer);

	void AddTexture(const std::string& name, RHITexture* texture);

	void RemoveTexture(const std::string& name, RHITexture* texture);

	void AddPipeline(const std::string& name, RHIPipeline* pipeline);

	void RemovePipeline(const std::string& name, RHIPipeline* pipeline);

	void AddRenderPass(const std::string& name, RHIRenderPass* renderPass);

	void RemoveRenderPass(const std::string& name, RHIRenderPass* renderPass);

	void AddFrameBuffer(const std::string& name, RHIFrameBuffer* frameBuffer);

	void RemoveFrameBuffer(const std::string& name, RHIFrameBuffer* frameBuffer);

	void AddDescriptor(const std::string& name, RHIDescriptor* descriptor);

	void RemoveDescriptor(const std::string& name, RHIDescriptor* descriptor);

	void AddAccelerationStructure(const std::string& name, AccelerationStructure* accelerationStructure);

	void RemoveAccelerationStructure(const std::string& name, AccelerationStructure* accelerationStructure);

	void AddAccelerationStructureGeometry(const std::string& name, AccelerationStructureGeometry* accelerationStructureGeometry);

	void RemoveAccelerationStructureGeometry(const std::string& name, AccelerationStructureGeometry* accelerationStructureGeometry);

	void AddSampler(const std::string& name, RHISampler* sampler);

	void RemoveSampler(const std::string& name, RHISampler* sampler);

	void AddCommandBuffer(const std::string& name, RHICommandBuffer* commandBuffer);

	void RemoveCommandBuffer(const std::string& name, RHICommandBuffer* commandBuffer);

	void AddFence(const std::string& name, RHIFence* fence);

	void RemoveFence(const std::string& name, RHIFence* fence);

	void AddSemaphore(const std::string& name, RHISemaphore* semaphore);

	void RemoveSemaphore(const std::string& name, RHISemaphore* semaphore);

private:

	std::unordered_map<std::string, RHIBuffer*> mProxyBufferMap;

	std::unordered_map<std::string, RHITexture*> mProxyTextureMap;

	std::unordered_map<std::string, RHIPipeline*> mProxyPipelineMap;

	std::unordered_map<std::string, RHIRenderPass*> mProxyRenderPassMap;

	std::unordered_map<std::string, RHIFrameBuffer*> mProxyFrameBufferMap;

	std::unordered_map<std::string, RHIDescriptor*> mProxyDescriptorMap;

	std::unordered_map<std::string, AccelerationStructure*> mProxyAccelerationStructureMap;

	std::unordered_map<std::string, AccelerationStructureGeometry*> mProxyAccelerationStructureGeometryMap;

	std::unordered_map<std::string, RHISampler*> mProxySamplerMap;

	std::unordered_map<std::string, RHICommandBuffer*> mProxyCommandBufferMap;

	std::unordered_map<std::string, RHIFence*> mProxyFenceMap;

	std::unordered_map<std::string, RHISemaphore*> mProxySemaphoreMap;

};